package com.fmy.springbootsecurity.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Array;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @version 1.0
 * @Author MR.fmy
 * @Description Jwt工具类
 * @Date 2019/5/13 0013 11:44
 **/
@Slf4j
public class JwtUtil {

    public final static String JWT_SECRET = "hugy54qwdb";

    private static final String EXP = "exp";

    private static final String PAYLOAD = "payload";

    /**
     * 生成token
     *
     * @param maxAge 有效时长 单位/毫秒
     * @param secret 秘钥
     * @return
     */
    public static String createToken(long maxAge, String secret, Map<String, Object> claimMap) {
        final Algorithm signer = Algorithm.HMAC256(secret);//生成签名
        JWTCreator.Builder builder = JWT.create();
        builder.withIssuer("Mr.fmy")
                .withSubject("login")
                .withExpiresAt(new Date(System.currentTimeMillis() + maxAge));
        setClaim(builder, claimMap);
        String token = builder.sign(signer);
        return token;
    }

    private static void setClaim(JWTCreator.Builder builder, Map<String, Object> claimMap) {
        for (String key : claimMap.keySet()) {
            Object value = claimMap.get(key);
            if (value instanceof String[]) {
                builder.withArrayClaim(key, (String[]) value);
            } else if (value instanceof Integer[]) {
                builder.withArrayClaim(key, (Integer[]) value);
            } else if (value instanceof Long[]) {
                builder.withArrayClaim(key, (Long[]) value);
            } else {
                //其余的一律使用String类型
                builder.withClaim(key, value.toString());
            }
        }
    }

    /**
     * 效验token
     *
     * @param token
     * @param secret HMAC256 加密的秘钥
     */
    public static boolean verifyToken(String token, String secret) {
        final Algorithm signer = Algorithm.HMAC256(secret);//生成签名
        JWTVerifier verifier = JWT.require(signer)
                .withIssuer("Mr.fmy")
                .build(); //Reusable verifier instance
        try {
            DecodedJWT jwt = verifier.verify(token);
        } catch (Exception e) {
            log.error("token验证错误", e);
            return false;
        }
        return true;
    }

    /**
     * 获取token中`Claim`存储的某个key值
     * @param token
     * @param key
     */
    public static Claim decode(String token,String key){
        DecodedJWT jwt = JWT.decode(token);
        Map<String, Claim> claims = jwt.getClaims();
        Claim claim = claims.get(key);
        return claim;
    }
}
